package Thread;

import java.util.concurrent.*;

/**
 * @author zp
 * @version 1.0
 * @description: TODO
 * @date 2022/5/25 19:03
 */
public class CompletableFutureTest {
//    supply开头：这种方法，可以返回异步线程执行之后的结果
//    run开头：这种不会返回结果，就只是执行线程任务

//    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
//    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
//
//    public static CompletableFuture<Void> runAsync(Runnable runnable);
//    public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);
    //自定义线程池
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(10,10,10, TimeUnit.SECONDS,new LinkedBlockingDeque<>(),Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());
    //不使用单元测试类的原因 单元测试跑完jvm就会关闭 主线程停止 无法测试异步线程
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        CompletableFuture<String> future  = CompletableFuture.supplyAsync(() -> {
//            int i = 0;
//            i=i/0;
//            return "我今天成功了";
//        }, executor);
        //可以接收两个参数 一个返回结果和可抛出异常 可以接收参数 但没有返回
        /**
         *      whenComplete(BiConsumer<? super T,? super Throwable> action)
         *      public CompletableFuture<T>     whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
         *      public CompletableFuture<T>     whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
         *      public CompletableFuture<T>     exceptionally(Function<Throwable,? extends T> fn)
         * 方法1和2的区别在于是否使用异步处理，2和3的区别在于是否使用自定义的线程池，
         * 前三个方法都会提供一个返回结果和可抛出异常，我们可以使用lambda表达式的来接收这两个参数，然后自己处理。
         * 方法4，接收一个可抛出的异常，且必须return一个返回值，类型与钻石表达式种的类型一样，
         *
         */
//        CompletableFuture<String> future1 = future.whenCompleteAsync((u,t)->{
//            if(t==null){
//                u=u+"异步调用";
//            }else {
//                System.out.println(t.getLocalizedMessage()+"我捕获了");
//            }
//        },executor);
//        System.out.println(future1.get());

        //需要自定义返回参数类型 自己处理异常
//        CompletableFuture<Integer> handle = future.handleAsync((u, t) -> {
//            if(t==null){
//                return u.length();
//            }
//            t.getStackTrace();
//            return -1;
//        }, executor);
//        System.out.println(handle.get());

        //如果直接不想处理异常 只想抛到外部处理可以使用以下方法
//        CompletableFuture<Integer> apply = future.thenApplyAsync((u) -> {
//            return u.length();
//        }, executor);
//        System.out.println(apply.get());

//        future.exceptionally(t->{
//            t.printStackTrace();
//            return "出错啊~";
//            //最终收尾的方法 不返回CompletableFuture<T>对象做后续处理 做最终结果 如果有异常 这个方法不捕获异常
//        }).thenAcceptAsync((u)->{
//            int x = u.length()+2;
//            System.out.println(x);
//        },executor);

        //获取所有完成结果——allOf
//        CompletableFuture<String> future1  = CompletableFuture.supplyAsync(() -> {
//            System.out.println("future1开始了");
//            try {
//                Thread.sleep(2000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("future1结束了");
//            return "future2你跑的快还是要等我";
//        }, executor);
//
//        CompletableFuture<String> future2  = CompletableFuture.supplyAsync(() -> {
//            System.out.println("future2开始了");
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("future2结束了");
//            return "future1我先走了";
//        }, executor);
//
//        CompletableFuture.allOf(future1,future2);
//        System.out.println(future1.join());
//        System.out.println(future2.join());


        CompletableFuture<String> future1  = CompletableFuture.supplyAsync(() -> {
            System.out.println("future1开始了");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("future1结束了");
            return "future2你跑的快还是要等我";
        }, executor);

        CompletableFuture<String> future2  = CompletableFuture.supplyAsync(() -> {
            System.out.println("future2开始了");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("future2结束了");
            return "future1我先走了";
        }, executor);
        //只要任意一个线程跑完 我就返回数据
        //如果最快完成的任务出现了异常，也会先返回异常，如果害怕出错可以加个exceptionally() 去处理一下可能发生的异常并设定默认返回值
        CompletableFuture.anyOf(future1,future2);
        System.out.println(future1.join());
        System.out.println(future2.join());
    }
}
